package Cryptointerface

import (
	"../Symmetric"
	"../UnSymmetric"
	"../hash"
	"crypto/rand"
	"math/big"
	"strings"
)

type YinchengCrypto struct {
	myhash         hash.HashInterface
	mysymmetric    Symmetric.SymmetricInterface
	myunsymmetric  UnSymmetric.UnSymmetricInterface
	password       string //密码
	privatekeypath string //私钥
	publickeypath  string //公钥
}

func (yc *YinchengCrypto) GetPassword() string {
	return yc.password
}

func Makerandomstr(min, max int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	result := []byte{}
	var length int
	if min < max {
		rnd, err := rand.Int(rand.Reader, big.NewInt(int64(max-min)))
		if err != nil {
			return ""
		}
		length = min + int(rnd.Uint64())
	} else if min == max {
		length = min
	} else {
		return ""
	}
	for i := 0; i < length; i++ {
		rrnd, err := rand.Int(rand.Reader, big.NewInt(100000000))
		if err != nil {
			return ""
		}
		//rrnd随机整数，对字符串长度求模，随机索引
		result = append(result, bytes[int(rrnd.Uint64())%len(str)])
	}
	return string(result)
}

//新建一个结构体，返回一个指针
func NewYinchengCryptoRead(hasharr []string, password string, pubpath, privpath string) *YinchengCrypto {
	yc := new(YinchengCrypto) //返回一个指针

	yc.myhash = new(hash.AllHash)
	yc.myhash.SetAlog(hasharr)

	yc.mysymmetric = new(Symmetric.DES3)
	yc.password = password

	yc.myunsymmetric = new(UnSymmetric.ECC)
	yc.myunsymmetric.Readprivatekey(privpath)
	yc.myunsymmetric.Readpublickey(pubpath)
	return yc
}

//新建一个结构体，返回一个指针
func NewYinchengCrypto(hasharr []string, passwordlength int, keytemppath string) *YinchengCrypto {
	yc := new(YinchengCrypto) //返回一个指针

	yc.myhash = new(hash.AllHash)
	yc.myhash.SetAlog(hasharr)

	yc.mysymmetric = new(Symmetric.DES3)
	yc.password = Makerandomstr(passwordlength, passwordlength)

	yc.myunsymmetric = new(UnSymmetric.ECC)
	yc.myunsymmetric.MakeKey(keytemppath+"\\pub.pem",
		keytemppath+"\\priv.pem")
	return yc
}

//新建一个结构体，返回一个指针
func NewYinchengServerCrypto(hasharr []string, passwordlength int, keytemppath string) *YinchengCrypto {
	yc := new(YinchengCrypto) //返回一个指针

	yc.myhash = new(hash.AllHash)
	yc.myhash.SetAlog(hasharr)

	yc.mysymmetric = new(Symmetric.DES3)
	yc.password = Makerandomstr(passwordlength, passwordlength)

	yc.myunsymmetric = new(UnSymmetric.ECC)
	yc.myunsymmetric.Readprivatekey(keytemppath)
	return yc
}

func NewYinchengClientCrypto(hasharr []string, password string, pubkeypath string) *YinchengCrypto {
	yc := new(YinchengCrypto) //返回一个指针

	yc.myhash = new(hash.AllHash)
	yc.myhash.SetAlog(hasharr)

	yc.mysymmetric = new(Symmetric.DES3)
	yc.password = password

	yc.myunsymmetric = new(UnSymmetric.ECC)
	yc.myunsymmetric.Readpublickey(pubkeypath)

	return yc
}
func (yc *YinchengCrypto) ToCryptoString(Data string) string {
	datahash := yc.myhash.GetStringHash(Data)
	Data += datahash                                         //数据+哈希
	cdata := yc.mysymmetric.EncryptString(Data, yc.password) //加密

	rtext, stext := yc.myunsymmetric.SignString(cdata)
	cdata += "#$#" + rtext
	cdata += "#$#" + stext
	return cdata

}
func (yc *YinchengCrypto) GetResultString(CryptoData string) (string, bool) {

	datalist := strings.Split(CryptoData, "#$#")
	if len(datalist) != 3 {
		return "", false
	} else {
		var istrust bool
		cdata, rtext, stext := datalist[0], datalist[1], datalist[2]
		istrust = yc.myunsymmetric.VerificationSignString(cdata, rtext, stext)
		if istrust {
			dedata := yc.mysymmetric.DecryptString(cdata, yc.password)
			if dedata != "" {
				data := dedata[:len(dedata)-128]
				//data+="1"
				hashdata := dedata[len(dedata)-128:]
				gethash := yc.myhash.GetStringHash(data)
				if gethash == hashdata {
					return data, true

				} else {
					return "", false
				}

			} else {
				return "", false
			}

		} else {
			return "", false
		}

	}

	return "", false

}
func (yc *YinchengCrypto) ToCrypto(Data []byte) []byte {
	return []byte{}
}
func (yc *YinchengCrypto) GetResult(CryptoData []byte) ([]byte, bool) {
	return []byte{}, true
}
